


class Protocol{

  static hex = new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F");
  static sn = 0

  static args = [0x11,  0x22, 0x04, 0x08,  0x99,  0x04,
     0x24, 0x16, 0x04,  0xAA,  0xBB,  0xCC,
     0xF0, 0x60,  0x61,  0xCD,  0xCF,
     0x80, 0x35,  0x2A];

  static copy(src,srcPos,dest,destPos,length){
    for(let i=srcPos,j=destPos;i<(srcPos+length);i++,j++){
      dest[j] = src[i];
    }
  }

  static encode(opCode,address,params){

    if (params == null) {
      params = new Uint8Array(9)
    } else if (params.length < 9) {
        let bytes = new Uint8Array(9)
        copy(params, 0, bytes, 0, params.length)
        params = bytes;
    }

    let transport = new Uint8Array(26)
    transport[0] = 0x5A
    transport[1] = 0x71
    transport[2] = 0x00
    transport[3] = 0x11
    transport[4] = 0x00
    transport[5] = 0x1F
    transport[6] = this.nextSn()
    transport[7] = ((address & 0x00FF0000) >> 16)
    transport[8] = ((address & 0x0000FF00) >> 8)
    transport[9] = (address & 0xFF)
    transport[10] = 0x00
    transport[11] = 0x00
    transport[12] = opCode
    this.copy(params, 0, transport, 13, params.length)
    transport[22] = 0x00
    let random = Math.floor(Math.random() * 1000) & 0xFF
    transport[23] = random
    this.encrypt1(transport, transport[23], 10, 22);
    this.encrypt2(transport, 4, 23);
    let crc = this.toCrc(transport)
    transport[24] = (((crc & 0xFF00) >> 8) & 0xFF)
    transport[25] = (crc & 0xFF)
    this.reversal(transport)
    console.log(this.toHexString(transport))
    return this.toAdvertiseUuId(transport);
  }


  static toAdvertiseUuId(bytes){
    let advertiesUuId = []
    for(let i=0;i<bytes.length;i++){
      let b1 = [0,0,bytes[i],bytes[i+1]]
      let hex = this.toHexString(b1)
      advertiesUuId.push(hex+"-0000-1000-8000-00805f9b34fb")
      i = i+1
    }
    console.log("advertiesUuId "+JSON.stringify(advertiesUuId))
    return advertiesUuId
  }

  static toHexString(uint8bytes){
    if(uint8bytes == null || uint8bytes == undefined)
      return "";
    let tempHex = "";
    for(let i=0;i<uint8bytes.length;i++){
      tempHex += (this.hex[((uint8bytes[i] & 0xF0) >> 4)] + this.hex[uint8bytes[i] & 0x0F]);
    }
    return tempHex;
  }


  static nextSn() {
    return this.sn++;
  }

  static toCrc(transport) {
    let crc = 0;
    for (let i = 0; i < transport.length - 2; i++) {
        crc += transport[i];
    }
    return crc & 0xFFFF;
  }


  static  encrypt1(list,random,begin,end) {
    for (let i = begin; i <= end; i++) {
        list[i] =  (list[i] ^ random);
    }

  }

  static  encrypt2(list,begin,end) {
    for (let i = begin; i <= end; i++) {
        list[i] =  (list[i] ^ this.args[i - begin]);
    }
  }

  
  static reversal(transport) {

    for (let i = 2; i < (transport.length - 1); i++) {
        let temp = transport[i];
        transport[i] = transport[i + 1];
        transport[i + 1] = temp;
        i = i + 1;
    }
  }


}

const _Protocol = Protocol;
export { _Protocol as Protocol };
